package cart

import (
	// "fmt"
	"strconv"
	"strings"

	"mall/common/moneyx"
	"mall/service/backend/common/utils/pointy"
	"mall/service/forum/api/internal/types"

	"github.com/shopspring/decimal"
	// "github.com/sirupsen/logrus"
)

// PackageAndCleanupHandler 组装、清理返回结果的handler
type PackageAndCleanupHandler struct {
	// 合成复用Next
	Next
}

// Do 组装、清理返回结果的逻辑
func (h *PackageAndCleanupHandler) Do(c *Context) (err error) {
	if len(c.Resp.List) == 0 {
		return
	}

	activityAmountMap := make(map[uint64][]decimal.Decimal)
	couponAmountMap := make(map[uint64][]decimal.Decimal)
	for _, info := range c.PricingInfos {
		// logrus.Info(fmt.Sprintf("PackageAndCleanupHandler PricingInfos: %+v", info))

		activityAmountMap[info.SkuId] = append(activityAmountMap[info.SkuId], info.ActivityAmount)
		couponAmountMap[info.SkuId] = append(couponAmountMap[info.SkuId], info.CouponAmount)
	}

	var isValid bool = true // 优惠有效
	var skuInfoList []*types.ShoppingCartItemInfo
	for _, skuInfo := range c.Resp.List {
		if skuInfo.Prefetched != nil && *skuInfo.Prefetched > 0 {
			continue
		}

		if skuInfo.SkuId != nil && *skuInfo.SkuId > 0 {
			var finalSkuAmount decimal.Decimal
			if skuAmount, ok := c.SkuAmountMap[*skuInfo.SkuId]; ok {
				finalSkuAmount = skuAmount
			}

			var finalActivityAmount decimal.Decimal
			if activityAmountList, ok := activityAmountMap[*skuInfo.SkuId]; ok {
				for _, activityAmount := range activityAmountList {
					finalActivityAmount = finalActivityAmount.Add(activityAmount)
				}
			}

			var finalCouponAmount decimal.Decimal
			if couponAmountList, ok := couponAmountMap[*skuInfo.SkuId]; ok {
				for _, couponAmount := range couponAmountList {
					finalCouponAmount = finalCouponAmount.Add(couponAmount)
				}
			}

			if finalActivityAmount.GreaterThan(finalSkuAmount) || finalCouponAmount.GreaterThan(finalSkuAmount) ||
				finalActivityAmount.Add(finalCouponAmount).GreaterThan(finalSkuAmount) {
				isValid = false
			}

			// skuInfo.SkuAmount = pointy.GetPointer(moneyx.FormatDecimal(finalSkuAmount.Mul(c.GemRatio), 2))
			// skuInfo.ActivityAmount = pointy.GetPointer(moneyx.FormatDecimal(finalActivityAmount.Mul(c.GemRatio), 2))
			// skuInfo.CouponAmount = pointy.GetPointer(moneyx.FormatDecimal(finalCouponAmount.Mul(c.GemRatio), 2))
			// skuInfo.DiscountAmount = pointy.GetPointer(moneyx.FormatDecimal(finalActivityAmount.Add(finalCouponAmount).
			// 	Mul(c.GemRatio), 2))
			// skuInfo.FinalAmount = pointy.GetPointer(moneyx.FormatDecimal(
			// 	finalSkuAmount.Sub(finalActivityAmount).Sub(finalCouponAmount).Mul(c.GemRatio), 2))
			skuInfo.SkuAmount = pointy.GetPointer(moneyx.FormatDecimal(finalSkuAmount, 2))
			skuInfo.ActivityAmount = pointy.GetPointer(moneyx.FormatDecimal(finalActivityAmount, 2))
			skuInfo.CouponAmount = pointy.GetPointer(moneyx.FormatDecimal(finalCouponAmount, 2))
			skuInfo.DiscountAmount = pointy.GetPointer(moneyx.FormatDecimal(finalActivityAmount.Add(finalCouponAmount), 2))
			skuInfo.FinalAmount = pointy.GetPointer(moneyx.FormatDecimal(
				finalSkuAmount.Sub(finalActivityAmount).Sub(finalCouponAmount), 2))
			skuInfoList = append(skuInfoList, skuInfo)
		}
	}
	c.Resp.List = skuInfoList

	c.Resp.PromotionValid = isValid

	// logrus.Info(fmt.Sprintf("PackageAndCleanupHandler pending Modifiers: ==========\n"))

	for _, info := range c.Modifiers {
		if info.Status > 0 {
			c.Resp.ModifierList = append(c.Resp.ModifierList, &types.OrderModifier{
				ActivityId:       pointy.GetPointer(uint64(info.ActivityId)),
				RuleId:           pointy.GetPointer(uint64(info.RuleId)),
				CouponId:         pointy.GetPointer(uint64(info.CouponId)),
				CouponTemplateId: pointy.GetPointer(uint64(info.CouponTemplateId)),
				// ActivityAmount:   pointy.GetPointer(info.ActivityAmount.Mul(c.GemRatio).Truncate(2).String()),
				// CouponAmount:     pointy.GetPointer(info.CouponAmount.Mul(c.GemRatio).Truncate(2).String()),
				ActivityAmount: pointy.GetPointer(moneyx.FormatDecimal(info.ActivityAmount, 2)),
				CouponAmount:   pointy.GetPointer(moneyx.FormatDecimal(info.CouponAmount, 2)),
			})
		} else {
			// logrus.Info(fmt.Sprintf("%+v", info))
		}
	}

	// logrus.Info(fmt.Sprintf("============================================================\n"))

	if c.ActivityAmount.GreaterThan(c.SkusAmount) {
		c.Resp.ActivityValid = false
	} else {
		c.Resp.ActivityValid = true
	}
	if c.CouponAmount.GreaterThan(c.SkusAmount) {
		c.Resp.CouponValid = false
	} else {
		c.Resp.CouponValid = true
	}
	if c.ActivityAmount.Add(c.CouponAmount).GreaterThan(c.SkusAmount) {
		c.Resp.FinalValid = false
	} else {
		c.Resp.FinalValid = true
	}

	var newActivityList []*types.PromotionActivityInfo
	for _, activityInfo := range c.Resp.ActivityList {
		if activityInfo.Status != nil {
			newActivityList = append(newActivityList, activityInfo)
		}
	}
	c.Resp.ActivityList = newActivityList

	var newCouponList []*types.CouponInfo
	var autoReceiveCouponIds *string
	for _, couponInfo := range c.Resp.CouponList {
		var couponIds []string
		if couponInfo.Status != nil {
			if couponInfo.CouponId == nil || *couponInfo.CouponId == 0 {
				couponIds = append(couponIds, strconv.FormatInt(int64(*couponInfo.TemplateId), 10))
			}
			newCouponList = append(newCouponList, couponInfo)
		}
		if len(couponIds) > 0 {
			autoReceiveCouponIds = pointy.GetPointer(strings.Join(couponIds, ","))
		}
	}
	c.Resp.CouponList = newCouponList
	c.Resp.AutoReceiveCouponIds = autoReceiveCouponIds

	// c.Resp.RetailAmount = pointy.GetPointer(c.SkusAmount.Truncate(2).String())
	// c.Resp.GemAmount = pointy.GetPointer(c.SkusAmount.Mul(c.GemRatio).Truncate(2).String())
	// c.Resp.ActivityAmount = pointy.GetPointer(c.ActivityAmount.Mul(c.GemRatio).Truncate(2).String())
	// c.Resp.CouponAmount = pointy.GetPointer(c.CouponAmount.Mul(c.GemRatio).Truncate(2).String())
	// c.Resp.Freight = pointy.GetPointer(c.Freight.Mul(c.GemRatio).Truncate(2).String())
	// c.Resp.FinalFreight = pointy.GetPointer(c.FinalFreight.Mul(c.GemRatio).Truncate(2).String())
	// c.Resp.FinalAmount =
	// 	pointy.GetPointer(c.FinalAmount.Add(c.FinalFreight).Mul(c.GemRatio).Truncate(2).String())
	c.Resp.RetailAmount = pointy.GetPointer(moneyx.FormatDecimal(c.SkusAmount, 2))
	c.Resp.ActivityAmount = pointy.GetPointer(moneyx.FormatDecimal(c.ActivityAmount, 2))
	c.Resp.CouponAmount = pointy.GetPointer(moneyx.FormatDecimal(c.CouponAmount, 2))
	c.Resp.Freight = pointy.GetPointer(moneyx.FormatDecimal(c.Freight, 2))
	c.Resp.FinalFreight = pointy.GetPointer(moneyx.FormatDecimal(c.FinalFreight, 2))
	c.Resp.FinalAmount =
		pointy.GetPointer(moneyx.FormatDecimal(c.FinalAmount.Add(c.FinalFreight), 2))

	if c.FinalAmount.Add(c.FinalFreight).Mul(c.GemRatio).GreaterThan(c.AccountGems) {
		c.Resp.BalanceValid = false
	} else {
		c.Resp.BalanceValid = true
	}

	return
}
